/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/*
 * ChartInternalFrame.java
 *
 * Created on 01.12.2009, 18:54:04
 */
package GUI.iFrames;

import input.IoToolbox;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFileChooser;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.ShapeUtilities;

import toolz.netCdfTools;

/**
 * 
 * @author Bunkowski
 */
public class GcmsInternalFrame extends javax.swing.JInternalFrame implements ChartMouseListener, MouseListener,
		MouseMotionListener, MouseWheelListener, DropTargetListener {

	public static final long serialVersionUID = 1L;

	public DropTarget dropTarget = new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this, true, null); // NO_UCD
	// TODO Remove unused code found by UCDetector
	// Vector<String> classLabels, xAchsisLabels;
	private Vector<Double> numericXAchsis;
	private Vector<Vector<Double>> dataLines = new Vector<Vector<Double>>();
	private String chartTitle = "GC-MS TIC", xAxisLabel = "Retention time", yAxisLabel = "";
	// DefaultCategoryDataset barDataset = new DefaultCategoryDataset();
	private XYSeriesCollection lineDataset = new XYSeriesCollection();
	public PlotOrientation plotorientation = PlotOrientation.VERTICAL;
	// TODO Remove unused code found by UCDetector
	// boolean livechart = false;
	private JFreeChart lineChart;
	private Point2D panStartPoint;
	private ChartPanel cp;
	private String initName = "";
	private Vector<String> filenames = new Vector<String>();

	// TODO Remove unused code found by UCDetector
	// HeatmapInternalFrame hmif = null;

	/** Creates new form ChartInternalFrame */
	public GcmsInternalFrame() {
		initComponents();
	}

	// TODO Remove unused code found by UCDetector
	// public GcmsInternalFrame(HeatmapInternalFrame hmif) {
	// initComponents();
	// //this.hmif = hmif;
	// }

	public void setChartTitle(String title) {
		chartTitle = title;
		lineChart.setTitle(title);
	}

	public void addCdfFile(String filename) {
		filenames.add(filename);
		Vector wrap = netCdfTools.readFile(filename);
		addSeries((String) wrap.get(0), (Vector) wrap.get(1), (Vector) wrap.get(2));

	}

	private void addSeries(String name, Vector<Double> dataLine, Vector<Double> numericXAchsis) {
		XYSeries series = new XYSeries(name);
		for (int j = 0; j < dataLine.size(); j++) {
			Double d = dataLine.get(j);
			series.add(numericXAchsis.get(j), d);
		}
		System.out.println("adding series");
		lineDataset.addSeries(series);
	}

	public void showAsLineChart() {
		if (numericXAchsis == null) {
			lineDataset.removeAllSeries();
			for (int i = 0; i < dataLines.size(); i++) {
				XYSeries series = new XYSeries(initName);
				for (int j = 0; j < dataLines.get(i).size(); j++) {
					Double d = dataLines.get(i).get(j);
					series.add(j, d);
				}
				System.out.println("adding series");
				lineDataset.addSeries(series);
			}
		} else {
			lineDataset.removeAllSeries();
			for (int i = 0; i < dataLines.size(); i++) {
				XYSeries series = new XYSeries(initName);
				for (int j = 0; j < dataLines.get(i).size(); j++) {
					Double d = dataLines.get(i).get(j);
					series.add(numericXAchsis.get(j), d);
				}
				System.out.println("adding series");
				lineDataset.addSeries(series);
			}
		}

		lineChart = ChartFactory.createXYLineChart(chartTitle, // Title
				xAxisLabel, // x-axis Label
				yAxisLabel, // y-axis Label
				lineDataset, // Dataset
				plotorientation, // Plot Orientation
				true, // Show Legend
				false, // Use tooltips
				false // Configure chart to generate URLs?
				);

		center.removeAll();
		cp = new ChartPanel(lineChart);
		center.add(cp);

		cp.addMouseListener(this);
		cp.addChartMouseListener(this);
		cp.addMouseWheelListener(this);
		cp.addMouseMotionListener(this);

	}

	private void updateChart() {
		showAsLineChart();
		validate();
	}

	/**
	 * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The
	 * content of this method is always regenerated by the Form Editor.
	 */
	private void initComponents() {

		buttonGroup1 = new javax.swing.ButtonGroup();
		buttonGroup2 = new javax.swing.ButtonGroup();
		buttonGroup3 = new javax.swing.ButtonGroup();
		center = new javax.swing.JPanel();
		jLabel2 = new javax.swing.JLabel();
		hButton = new javax.swing.JToggleButton();
		vButton = new javax.swing.JToggleButton();
		saveButton = new javax.swing.JButton();
		jLabel1 = new javax.swing.JLabel();
		gcButton = new javax.swing.JToggleButton();
		mccButton = new javax.swing.JToggleButton();
		jButton1 = new javax.swing.JButton();

		setClosable(true);
		setIconifiable(true);
		setMaximizable(true);
		setResizable(true);
		setTitle("GC/MS Plot panel");
		addInternalFrameListener(new javax.swing.event.InternalFrameListener() {
			public void internalFrameActivated(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameClosing(javax.swing.event.InternalFrameEvent evt) {
				formInternalFrameClosing(evt);
			}

			public void internalFrameDeactivated(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameDeiconified(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameIconified(javax.swing.event.InternalFrameEvent evt) {
			}

			public void internalFrameOpened(javax.swing.event.InternalFrameEvent evt) {
			}
		});

		center.setLayout(new javax.swing.BoxLayout(center, javax.swing.BoxLayout.PAGE_AXIS));

		jLabel2.setText("Orientation:");

		buttonGroup2.add(hButton);
		hButton.setText("H");
		hButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		hButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				hButtonActionPerformed(evt);
			}
		});

		buttonGroup2.add(vButton);
		vButton.setText("V");
		vButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		vButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				vButtonActionPerformed(evt);
			}
		});

		saveButton.setText("save");
		saveButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		saveButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				saveButtonActionPerformed(evt);
			}
		});

		jLabel1.setText("RT:");

		buttonGroup3.add(gcButton);
		gcButton.setText("GC");
		gcButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		gcButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				gcButtonActionPerformed(evt);
			}
		});

		buttonGroup3.add(mccButton);
		mccButton.setText("MCC");
		mccButton.setMargin(new java.awt.Insets(2, 5, 2, 5));
		mccButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				mccButtonActionPerformed(evt);
			}
		});

		jButton1.setText("ChromA");
		jButton1.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				jButton1ActionPerformed(evt);
			}
		});

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addComponent(center, javax.swing.GroupLayout.DEFAULT_SIZE, 503, Short.MAX_VALUE)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(jLabel2)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(hButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(vButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
								.addComponent(jLabel1)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(gcButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(mccButton)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 156,
										Short.MAX_VALUE).addComponent(jButton1)
								.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(saveButton).addContainerGap()));
		layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
				layout.createSequentialGroup()
						.addContainerGap()
						.addGroup(
								layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
										.addComponent(jLabel2).addComponent(hButton).addComponent(vButton)
										.addComponent(saveButton).addComponent(jLabel1).addComponent(gcButton)
										.addComponent(mccButton).addComponent(jButton1))
						.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
						.addComponent(center, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE)));

		pack();
	}// </editor-fold>//GEN-END:initComponents

	private void hButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_hButtonActionPerformed
		plotorientation = PlotOrientation.HORIZONTAL;
		updateChart();
	}// GEN-LAST:event_hButtonActionPerformed

	private void vButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_vButtonActionPerformed
		plotorientation = PlotOrientation.VERTICAL;
		updateChart();
	}// GEN-LAST:event_vButtonActionPerformed

	private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_saveButtonActionPerformed
		JFileChooser chooser = new JFileChooser();
		chooser.setSelectedFile(new File(chartTitle + ".png"));
		chooser.setDialogType(JFileChooser.SAVE_DIALOG);
		int returnVal = chooser.showOpenDialog(null);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				java.io.File file = chooser.getSelectedFile();
				if (!file.toString().endsWith(".png")) {
					file = new java.io.File(file.getPath() + ".png");
				}
				ChartRenderingInfo info = new ChartRenderingInfo();
				ChartUtilities.saveChartAsPNG(file, lineChart, 1024, 768, info);
			} catch (IOException ex) {
				Logger.getLogger(GcmsInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
			}
		}
	}

	// public void saveToFolder(String folder) {
	// if (chartTitle.contains("\\")) {
	// chartTitle = chartTitle.replace("\\", "-");
	// }
	// if (chartTitle.contains(".")) {
	// chartTitle = chartTitle.replace(".", "_");
	// }
	// File file = new File(folder + "\\" + chartTitle.trim() + ".png");
	// try {
	//
	// ChartRenderingInfo info = new ChartRenderingInfo();
	// ChartUtilities.saveChartAsPNG(file, lineChart, 1024, 768, info);
	// } catch (IOException ex) {
	// Logger.getLogger(GcmsInternalFrame.class.getName()).log(Level.SEVERE, null, ex);
	// }
	// }// GEN-LAST:event_saveButtonActionPerformed

	private void formInternalFrameClosing(javax.swing.event.InternalFrameEvent evt) {// GEN-FIRST:event_formInternalFrameClosing
	}// GEN-LAST:event_formInternalFrameClosing

	private void mccButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_mccButtonActionPerformed
		double A = 7.92065;
		double B = 2.60168;
		double C = -2.58105;
		XYSeriesCollection newSC = new XYSeriesCollection();
		for (int i = 0; i < lineDataset.getSeriesCount(); i++) {
			XYSeries series = lineDataset.getSeries(i);
			XYSeries newSeries = new XYSeries(series.getKey());
			for (int j = 0; j < series.getItemCount(); j++) {
				XYDataItem item = series.getDataItem(j);
				double x = item.getXValue();
				double y = item.getYValue();
				if (netCdfTools.GcToMcc(x, A, B, C) > 500) {
					break;
				}
				newSeries.add(netCdfTools.GcToMcc(x, A, B, C), y);
			}
			newSC.addSeries(newSeries);
		}
		lineDataset.removeAllSeries();
		for (Object o : newSC.getSeries()) {
			XYSeries series = (XYSeries) o;
			lineDataset.addSeries(series);
		}

	}// GEN-LAST:event_mccButtonActionPerformed

	private void gcButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_gcButtonActionPerformed
		XYSeriesCollection newSC = new XYSeriesCollection();
		for (int i = 0; i < lineDataset.getSeriesCount(); i++) {
			XYSeries series = lineDataset.getSeries(i);
			XYSeries newSeries = new XYSeries(series.getKey());
			for (int j = 0; j < series.getItemCount(); j++) {
				XYDataItem item = series.getDataItem(j);
				double x = item.getXValue();
				double y = item.getYValue();
				if (netCdfTools.MccToGc(x) >= 0) {
					newSeries.add(netCdfTools.MccToGc(x), y);
				}
			}
			newSC.addSeries(newSeries);
		}
		lineDataset.removeAllSeries();
		for (Object o : newSC.getSeries()) {
			XYSeries series = (XYSeries) o;
			lineDataset.addSeries(series);
		}
	}// GEN-LAST:event_gcButtonActionPerformed

	private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jButton1ActionPerformed
		// TICPeakfinderWrapper tpfw = new TICPeakfinderWrapper();
		// List<double[]> peaks = tpfw.getPeaksFor(new File(filenames.get(0)), new
		// File("cfg/TICPeakFinder.properties"));

		// for (double[] da : peaks) {
		// System.out.println((da[0] / 60.0) + " / " + da[1]);
		// }

	}// GEN-LAST:event_jButton1ActionPerformed
		// Variables declaration - do not modify//GEN-BEGIN:variables

	private javax.swing.ButtonGroup buttonGroup1;
	private javax.swing.ButtonGroup buttonGroup2;
	private javax.swing.ButtonGroup buttonGroup3;
	private javax.swing.JPanel center;
	private javax.swing.JToggleButton gcButton;
	private javax.swing.JToggleButton hButton;
	private javax.swing.JButton jButton1;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JLabel jLabel2;
	private javax.swing.JToggleButton mccButton;
	private javax.swing.JButton saveButton;
	private javax.swing.JToggleButton vButton;

	// End of variables declaration//GEN-END:variables

	public void dragEnter(DropTargetDragEvent dtde) {
	}

	public void dragOver(DropTargetDragEvent dtde) {
	}

	public void dropActionChanged(DropTargetDragEvent dtde) {
	}

	public void dragExit(DropTargetEvent dte) {
	}

	public void drop(DropTargetDropEvent evt) {

		try {
			Transferable t = evt.getTransferable();
			String drop = (String) t.getTransferData(DataFlavor.stringFlavor);
			Vector<File> files = IoToolbox.decodeTabbedFileString(drop);
			for (int i = 0; i < files.size(); i++) {
				File file = files.elementAt(i);
				if (file.toString().endsWith(".cdf") || file.toString().endsWith(".CDF")) {
					addCdfFile(file.getPath());
				}
			}

			// addInformationFromDrop(drop);
		} catch (UnsupportedFlavorException ex) {
		} catch (IOException ex) {
		}
	}

	public void mousePressed(MouseEvent e) {
		if (e.getButton() == 2) {
			cp.setDomainZoomable(false);
			cp.setRangeZoomable(false);
			Rectangle2D dataArea = cp.getScreenDataArea();
			Point2D point = e.getPoint();
			if (dataArea.contains(point)) {
				this.panStartPoint = point;
			}
		}

	}

	public void mouseReleased(MouseEvent e) {

		this.panStartPoint = null;
		cp.setDomainZoomable(true);
		cp.setRangeZoomable(true);

	}

	public void mouseDragged(MouseEvent e) {
		if (this.panStartPoint != null) {
			Rectangle2D scaledDataArea = this.cp.getScreenDataArea();

			this.panStartPoint = ShapeUtilities.getPointInRectangle(this.panStartPoint.getX(),
					this.panStartPoint.getY(), scaledDataArea);
			Point2D panEndPoint = ShapeUtilities.getPointInRectangle(e.getX(), e.getY(), scaledDataArea);

			// horizontal pan

			XYPlot hvp = cp.getChart().getXYPlot();
			ValueAxis xAxis = hvp.getDomainAxis();

			if (xAxis != null) {
				double translatedStartPoint = xAxis.java2DToValue((float) this.panStartPoint.getX(), scaledDataArea,
						hvp.getDomainAxisEdge());
				double translatedEndPoint = xAxis.java2DToValue((float) panEndPoint.getX(), scaledDataArea,
						hvp.getDomainAxisEdge());
				double dX = translatedStartPoint - translatedEndPoint;

				double oldMin = xAxis.getLowerBound();
				double newMin = oldMin + dX;

				double oldMax = xAxis.getUpperBound();
				double newMax = oldMax + dX;

				xAxis.setLowerBound(newMin);
				xAxis.setUpperBound(newMax);
			}

			// vertical pan (1. Y-Axis)

			XYPlot vvp = cp.getChart().getXYPlot();
			ValueAxis yAxis = vvp.getRangeAxis();

			if (yAxis != null) {
				double translatedStartPoint = yAxis.java2DToValue((float) this.panStartPoint.getY(), scaledDataArea,
						vvp.getRangeAxisEdge());
				double translatedEndPoint = yAxis.java2DToValue((float) panEndPoint.getY(), scaledDataArea,
						vvp.getRangeAxisEdge());
				double dY = translatedStartPoint - translatedEndPoint;

				double oldMin = yAxis.getLowerBound();
				double newMin = oldMin + dY;

				double oldMax = yAxis.getUpperBound();
				double newMax = oldMax + dY;

				yAxis.setLowerBound(newMin);
				yAxis.setUpperBound(newMax);
			}

			// for the next time
			this.panStartPoint = panEndPoint;
		}
	}

	public void chartMouseClicked(ChartMouseEvent arg0) {
	}

	public void chartMouseMoved(ChartMouseEvent arg0) {
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	public void mouseWheelMoved(MouseWheelEvent e) {
		if (!(e.isAltDown() || e.isControlDown() || e.isShiftDown())) {
			XYPlot plot = cp.getChart().getXYPlot();
			double xViewSize = plot.getDomainAxis().getUpperBound() - plot.getDomainAxis().getLowerBound();

			double yViewSize = plot.getRangeAxis().getUpperBound() - plot.getRangeAxis().getLowerBound();

			if (e.getWheelRotation() > 0) {
				xViewSize *= -1;
				yViewSize *= -1;
			}

			plot.getDomainAxis().setUpperBound(plot.getDomainAxis().getUpperBound() - xViewSize / 20);
			plot.getDomainAxis().setLowerBound(plot.getDomainAxis().getLowerBound() + xViewSize / 20);
			plot.getRangeAxis().setUpperBound(plot.getRangeAxis().getUpperBound() - yViewSize / 20);
			plot.getRangeAxis().setLowerBound(plot.getRangeAxis().getLowerBound() + yViewSize / 20);
		}
	}
}
